package com.sws.worktive;

import java.util.List;

import org.apache.http.NameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.sws.worktive.adapters.JobListAdapter;
import com.sws.worktive.bitmaploading.ImageLoader;
import com.sws.worktive.job_advance_search.JobSearchFetcher;
import com.sws.worktive.job_advance_search.JobSearchRequestBody;
import com.sws.worktive.job_service.BaseFetcher.JobReceiverListener;
import com.sws.worktive.job_service.JobListJsonParser.JobData;
import com.sws.worktive.jobs_fetcher.JobFetcher;
import com.sws.worktive.model.Jobs;
import com.sws.worktive.task.ServerDownload;
import com.sws.worktive.task.ServerResponse;
import com.sws.worktive.util.ConnectionDector;
import com.sws.worktive.util.Constant;
import com.sws.worktive.util.JobDialog;
import com.sws.worktive.volley.MyVolley;

public class ViewFragment extends BaseFragment implements OnItemClickListener,ServerResponse {

	ListView listJobs;
	public JobListAdapter jobAdapter;

	private Animator mCurrentAnimator;
	private int mShortAnimationDuration;

	FrameLayout fl_container;

	ImageView expandedImageView;
	List<NameValuePair> valuePairs;
	
	private final String JOB_LIST_REQUEST_TAG = "job_list_request_tag";
	private final String JOB_SEARCH_LIST_REQUEST_TAG = "job_search_list_request_tag";
	
	private boolean shouldHideProgressBar;
	private ProgressBar mProgressBar;
	
	JobSearchRequestBody requestBody;
	
	//=======================API=======================
	
	public static ViewFragment newInstance(
			FragmentManager fragmentManager, 
			String fragmentTag,
			JobSearchRequestBody requestBody){
		ViewFragment viewFragment= (ViewFragment) fragmentManager.findFragmentByTag(fragmentTag);
		if (viewFragment == null) {
			viewFragment = new ViewFragment();
			viewFragment.requestBody = requestBody;
			return viewFragment;
		}
		return null;
	}
	
	public static ViewFragment newInstance(
			FragmentManager fragmentManager, 
			String fragmentTag){
		return newInstance(fragmentManager, fragmentTag, null);
	}
	
	public void updateJobData(JobData[] jobDatas){
		jobAdapter.clearList();
		for (JobData jobData : jobDatas) jobAdapter.addJObs(jobData);
		jobAdapter.notifyDataSetChanged();
	}
	
	public void fetchJobList() {
		showProgressBar();
		if (jobAdapter!= null) jobAdapter.clearList().notifyDataSetChanged();
		new JobFetcher(getActivity()).fetchJobs(JOB_LIST_REQUEST_TAG, new JobReceiverListener() {
			@Override
			public void jobListReceived(JobData[] jobDatas) {
				hideProgressBar();
				if(jobDatas != null) updateJobData(jobDatas);
			}
		});
	}
	
	public void fetchSearchJobList(JobSearchRequestBody requestBody){
		showProgressBar();
		new JobSearchFetcher(getActivity())
		.fetchJobSearch(
				JOB_SEARCH_LIST_REQUEST_TAG, 
				requestBody,
				new JobReceiverListener() {
					@Override
					public void jobListReceived(JobData[] jobDatas) {
						hideProgressBar();
						if (jobDatas != null) updateJobData(jobDatas);
					}
				});
	}

	//=======================Life Cycle=======================

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		jobAdapter = new JobListAdapter(getActivity());

		mShortAnimationDuration = getResources().getInteger(
				android.R.integer.config_shortAnimTime);
		
		if (((DrawerFragment) getActivity()).arrJobs.size() == 0) {
			ConnectionDector connectionDector = new ConnectionDector(ViewFragment.this.getActivity());
			if (connectionDector.isConnectingToInternet()) {
				if (requestBody !=null) {
					fetchSearchJobList(requestBody);
				}else {
					fetchJobList();
				}
			} else {
				Toast.makeText(ViewFragment.this.getActivity(),getResources().getString(R.string.no_internet_connection), Toast.LENGTH_SHORT).show();
			}
		} else {
			jobAdapter.notifyDataSetChanged();
		}
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		
		View view = inflater.inflate(R.layout.view_screen, container, false);

		fl_container = (FrameLayout) view.findViewById(R.id.container);
		expandedImageView = (ImageView) view.findViewById(R.id.expanded_image);
		listJobs = (ListView) view.findViewById(R.id.view_list);
		listJobs.setOnItemClickListener(this);
		listJobs.setAdapter(jobAdapter);
		
		mProgressBar = (ProgressBar)view.findViewById(R.id.progressBarViewScreen);
		if (shouldHideProgressBar) mProgressBar.setVisibility(View.GONE);
		
		return view;
		
	}
	
	private void hideProgressBar(){
		View view = getView();
		if(view != null)view.findViewById(R.id.progressBarViewScreen).setVisibility(View.GONE);;
		shouldHideProgressBar = true;
	}
	
	private void showProgressBar(){
		View view = getView();
		if(view != null)view.findViewById(R.id.progressBarViewScreen).setVisibility(View.VISIBLE);;
		shouldHideProgressBar = false;
	}

	@Override
	public void onDestroyView() {
		super.onDestroyView();
		if (this.isRemoving()) {
			MyVolley.getMyVolley(getActivity()).cancelRequestWithTag(JOB_LIST_REQUEST_TAG);
			MyVolley.getMyVolley(getActivity()).cancelRequestWithTag(JOB_SEARCH_LIST_REQUEST_TAG);
		}
		
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
		FragmentTransaction transaction = getChildFragmentManager()
				.beginTransaction();
		Fragment dialogFragment = getChildFragmentManager().findFragmentByTag(
				Constant.JOB_DIALOG_FRAGMENT);
		if (dialogFragment != null) {
			transaction.remove(dialogFragment);
		}
		transaction.addToBackStack(null);

		JobData jobData = jobAdapter.getJobDatas().get(arg2);
		
		String isImage = jobData.isIamage; 
				
		if (isImage.equals("0")) {
			JobDialog dialogWindow = JobDialog.newInstance(isImage, jobData.description);
			dialogWindow.show(transaction, Constant.JOB_DIALOG_FRAGMENT);
		} else if (isImage.equals("1")) {
			JobDialog dialogWindow = JobDialog.newInstance(isImage, jobData.imageUrl);
			dialogWindow.show(transaction, Constant.JOB_DIALOG_FRAGMENT);
		}

	}

	@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
	public void zoomImageFromThumb1(final ImageView thumbView, String url,
			ImageLoader imageLoader) {
		// If there's an animation in progress, cancel it immediately and
		// proceed with this one.
		if (mCurrentAnimator != null) {
			mCurrentAnimator.cancel();
		}

		// Load the high-resolution "zoomed-in" image.
		imageLoader.DisplayImage(expandedImageView, url);

		// Calculate the starting and ending bounds for the zoomed-in image.
		// This step
		// involves lots of math. Yay, math.
		final Rect startBounds = new Rect();
		final Rect finalBounds = new Rect();
		final Point globalOffset = new Point();

		// The start bounds are the global visible rectangle of the thumbnail,
		// and the
		// final bounds are the global visible rectangle of the container view.
		// Also
		// set the container view's offset as the origin for the bounds, since
		// that's
		// the origin for the positioning animation properties (X, Y).
		thumbView.getGlobalVisibleRect(startBounds);
		fl_container.getGlobalVisibleRect(finalBounds, globalOffset);
		startBounds.offset(-globalOffset.x, -globalOffset.y);
		finalBounds.offset(-globalOffset.x, -globalOffset.y);

		// Adjust the start bounds to be the same aspect ratio as the final
		// bounds using the
		// "center crop" technique. This prevents undesirable stretching during
		// the animation.
		// Also calculate the start scaling factor (the end scaling factor is
		// always 1.0).
		float startScale;
		if ((float) finalBounds.width() / finalBounds.height() > (float) startBounds
				.width() / startBounds.height()) {
			// Extend start bounds horizontally
			startScale = (float) startBounds.height() / finalBounds.height();
			float startWidth = startScale * finalBounds.width();
			float deltaWidth = (startWidth - startBounds.width()) / 2;
			startBounds.left -= deltaWidth;
			startBounds.right += deltaWidth;
		} else {
			// Extend start bounds vertically
			startScale = (float) startBounds.width() / finalBounds.width();
			float startHeight = startScale * finalBounds.height();
			float deltaHeight = (startHeight - startBounds.height()) / 2;
			startBounds.top -= deltaHeight;
			startBounds.bottom += deltaHeight;
		}

		// Hide the thumbnail and show the zoomed-in view. When the animation
		// begins,
		// it will position the zoomed-in view in the place of the thumbnail.
		thumbView.setAlpha(0f);
		expandedImageView.setVisibility(View.VISIBLE);

		// Set the pivot point for SCALE_X and SCALE_Y transformations to the
		// top-left corner of
		// the zoomed-in view (the default is the center of the view).
		expandedImageView.setPivotX(0f);
		expandedImageView.setPivotY(0f);

		// Construct and run the parallel animation of the four translation and
		// scale properties
		// (X, Y, SCALE_X, and SCALE_Y).
		AnimatorSet set = new AnimatorSet();
		set.play(
				ObjectAnimator.ofFloat(expandedImageView, View.X,
						startBounds.left, finalBounds.left))
				.with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
						startBounds.top, finalBounds.top))
				.with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
						startScale, 1f))
				.with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y,
						startScale, 1f));
		set.setDuration(mShortAnimationDuration);
		set.setInterpolator(new DecelerateInterpolator());
		set.addListener(new AnimatorListenerAdapter() {
			@Override
			public void onAnimationEnd(Animator animation) {
				mCurrentAnimator = null;
			}

			@Override
			public void onAnimationCancel(Animator animation) {
				mCurrentAnimator = null;
			}
		});
		set.start();
		mCurrentAnimator = set;

		// Upon clicking the zoomed-in image, it should zoom back down to the
		// original bounds
		// and show the thumbnail instead of the expanded image.
		final float startScaleFinal = startScale;
		expandedImageView.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				if (mCurrentAnimator != null) {
					mCurrentAnimator.cancel();
				}

				// Animate the four positioning/sizing properties in parallel,
				// back to their
				// original values.
				AnimatorSet set = new AnimatorSet();
				set.play(
						ObjectAnimator.ofFloat(expandedImageView, View.X,
								startBounds.left))
						.with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
								startBounds.top))
						.with(ObjectAnimator.ofFloat(expandedImageView,
								View.SCALE_X, startScaleFinal))
						.with(ObjectAnimator.ofFloat(expandedImageView,
								View.SCALE_Y, startScaleFinal));
				set.setDuration(mShortAnimationDuration);
				set.setInterpolator(new DecelerateInterpolator());
				set.addListener(new AnimatorListenerAdapter() {
					@Override
					public void onAnimationEnd(Animator animation) {
						thumbView.setAlpha(1f);
						expandedImageView.setVisibility(View.GONE);
						mCurrentAnimator = null;
					}

					@Override
					public void onAnimationCancel(Animator animation) {
						thumbView.setAlpha(1f);
						expandedImageView.setVisibility(View.GONE);
						mCurrentAnimator = null;
					}
				});
				set.start();
				mCurrentAnimator = set;
			}
		});
	}

	@Override
	public void httpResponse(JSONObject jsonObject, String requestTag) {
		if (requestTag.equals(Constant.TAG_JOB_REQUEST)) {
			if (jsonObject != null) {
				new JsonParser4RJobs().execute(jsonObject);
			}
		} else if (requestTag.equals(Constant.TAG_CATEGORY_REQUEST)) {
			if (jsonObject != null) {
				((DrawerFragment) getActivity()).startJsonParser4RCategory(jsonObject);
			}
		}

	}

	// Parsing JSON for Jobs

	class JsonParser4RJobs extends AsyncTask<JSONObject, Jobs, Void> {

		Jobs jobs = null;

		public JsonParser4RJobs() {
			Log.v("Json Parser", "constructor");
		}

		@Override
		protected Void doInBackground(JSONObject... params) {
			try {
				final JSONObject jsonObj = new JSONObject(params[0].toString());
				int status = jsonObj.optInt(Constant.STATUS);

				switch (status) {
				case 0:
					getActivity().runOnUiThread(new Runnable() {

						@Override
						public void run() {

							Toast.makeText(getActivity(),
									jsonObj.optString(Constant.MESSAGE),
									Toast.LENGTH_SHORT).show();
						}
					});
					break;
				case 1:

					JSONArray jsonArray = jsonObj.getJSONArray(Constant.JOBS);
					for (int i = 0; i < jsonArray.length(); i++) {
						JSONObject jsonObject = jsonArray.getJSONObject(i);
						jobs = new Jobs();
						jobs.setDescription(jsonObject
								.optString(Constant.DESCRIPTION));
						jobs.setLatitude(jsonObject
								.optString(Constant.LATITUDE));
						jobs.setLongitude(jsonObject
								.optString(Constant.LONGITUDE));
						jobs.setJobType(jsonObject.optString(Constant.JOB_TYPE));
						jobs.setIsImage(jsonObject.optString(Constant.IS_IMAGE));
						if (jsonObject.optString(Constant.IS_IMAGE).equals("1")) {
							jobs.setImgThumUrl(jsonObject
									.optString(Constant.THUMB_IMAGE_URL));
							jobs.setImgUrl(jsonObject
									.optString(Constant.IMAGE_URL));
						}
						jobs.setExpireDate(jsonObject
								.optString(Constant.EXPIRE_DATE));
						jobs.setAddedDate(jsonObject
								.optString(Constant.ADDED_DATE));
						jobs.setLastModifiedDate(jsonObject
								.optString(Constant.LAST_MODIFIED));
						jobs.setCity(jsonObject.optString(Constant.CITY));
						jobs.setState(jsonObject.optString(Constant.STATE));
						jobs.setStateCode(jsonObject
								.optString(Constant.STATECODE));

						publishProgress(jobs);
					}

					break;

				default:
					break;
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			}

			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			super.onPostExecute(result);

			if (((DrawerFragment) getActivity()).arrCategories!=null && ((DrawerFragment) getActivity()).arrCategories.size() != 0) {
				if (((DrawerFragment) getActivity()).mProgressDialog.isShowing()) {
					((DrawerFragment) getActivity()).mProgressDialog.dismiss();
				}
			} else {
				ServerDownload serverDownload = new ServerDownload(
						getActivity(), ViewFragment.this,
						Constant.TAG_CATEGORY_REQUEST);
				serverDownload.execute(valuePairs);
			}

		}

	}

}
